package com.sparrow.common.ai.behaviortree.editor;

import javax.swing.*;
import javax.swing.tree.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;
import java.util.ArrayList;

public class BehaviorTreeEditor extends JFrame {
    private JTree tree;
    private DefaultTreeModel treeModel;
    private DefaultMutableTreeNode root;

    private static int width = 1000;
    private static int height = 800;

    public BehaviorTreeEditor() {
        setTitle("行为树编辑器");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(width, height);

        root = new DefaultMutableTreeNode("Selector");
        treeModel = new DefaultTreeModel(root);
        tree = new JTree(treeModel);
        tree.setDragEnabled(true);
        tree.setDropMode(DropMode.ON_OR_INSERT); // 支持放置到节点上或之间
        tree.setTransferHandler(new TreeTransferHandler());

        JScrollPane scrollPane = new JScrollPane(tree);
        add(scrollPane, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel();
        JButton saveButton = new JButton("保存文件");
        JButton loadButton = new JButton("加载文件");
        saveButton.addActionListener(e -> saveToFile());
        loadButton.addActionListener(e -> loadFromFile());

        buttonPanel.add(saveButton);
        buttonPanel.add(loadButton);

        add(buttonPanel, BorderLayout.SOUTH);

        // 添加右键菜单支持
        JPopupMenu popupMenu = new JPopupMenu();
        JMenuItem renameItem = new JMenuItem("编辑节点");
        JMenuItem deleteItem = new JMenuItem("删除节点");
        JMenuItem selectorItem = new JMenuItem("添加Selector节点");
        JMenuItem sequenceItem = new JMenuItem("添加Sequence节点");
        JMenuItem parallelItem = new JMenuItem("添加Parallel节点");
        JMenuItem ConditionDecorateItem = new JMenuItem("添加ConditionDecorate节点");
        JMenuItem actionItem = new JMenuItem("添加Action节点");
        JMenuItem conditionItem = new JMenuItem("添加Condition节点");
        JMenuItem paramItem = new JMenuItem("添加节点参数");

        popupMenu.add(renameItem);
        popupMenu.add(deleteItem);
        popupMenu.add(selectorItem);
        popupMenu.add(actionItem);
        popupMenu.add(sequenceItem);
        popupMenu.add(parallelItem);
        popupMenu.add(conditionItem);
        popupMenu.add(paramItem);
        popupMenu.add(ConditionDecorateItem);


        parallelItem.addActionListener(e -> {
            addNode("Parallel");
        });
        selectorItem.addActionListener(e -> {
            addNode("Selector");
        });
        sequenceItem.addActionListener(e -> {
            addNode("Sequence");
        });
        conditionItem.addActionListener(e -> {
            addNodeWithClass("Condition");
        });
        actionItem.addActionListener(e -> {
            addNodeWithClass("Action");
        });
        paramItem.addActionListener(e -> {
            addNodeParam();
        });
        ConditionDecorateItem.addActionListener(e -> {
            addNode("ConditionDecorate");
        });

        renameItem.addActionListener(e -> {
            DefaultMutableTreeNode selected = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
            if (selected == null) {
                JOptionPane.showMessageDialog(this, "请先选择一个节点！");
                return;
            }
            if (selected.isRoot()) {
                JOptionPane.showMessageDialog(this, "根节点不允许重命名！");
                return;
            }
            String newName = JOptionPane.showInputDialog(this, "输入新的节点名称:", selected.toString());
            if (newName != null && !newName.trim().isEmpty()) {
                selected.setUserObject(newName.trim());
                treeModel.nodeChanged(selected);
            }
        });

        deleteItem.addActionListener(e -> {
            DefaultMutableTreeNode selected = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
            if (selected == null || selected.isRoot()) {
                JOptionPane.showMessageDialog(this, "请先选择一个非根节点！");
                return;
            }

            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selected.getParent();
            if (parent != null) {
                treeModel.removeNodeFromParent(selected);
                TreePath parentPath = new TreePath(treeModel.getPathToRoot(parent));
                tree.setSelectionPath(parentPath);
            }
        });

        tree.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) { // Windows/Linux
                    showMenu(e);
                }
            }

            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) { // macOS
                    showMenu(e);
                }
            }

            private void showMenu(MouseEvent e) {
                int row = tree.getRowForLocation(e.getX(), e.getY());
                if (row == -1) return;
                tree.setSelectionRow(row); // 选中右键点击的节点
                popupMenu.show(tree, e.getX(), e.getY());
            }
        });

        // 获取屏幕尺寸
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        // 计算窗口的初始位置，使其居中
        setLocation((screenSize.width) / 2 - (width / 2),
                (screenSize.height) / 2 - (height / 2));
    }

    private void addNode(String type) {
        DefaultMutableTreeNode selected = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selected == null) selected = root;
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(type);
        selected.add(newNode);
        treeModel.reload(selected);
    }

    private void addNodeWithClass(String type) {
        String className = JOptionPane.showInputDialog(this, "请输入类名:", "com.example.My" + type);
        if (className == null || className.trim().isEmpty()) return;

        DefaultMutableTreeNode selected = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selected == null) selected = root;

        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(type + " class=\"" + className + "\"");

        selected.add(newNode);
        treeModel.reload(selected);
    }

    private void addNodeParam() {
        DefaultMutableTreeNode selected = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selected == null || selected.isRoot()) {
            return;
        }
        int option = JOptionPane.YES_OPTION;
        while (option == JOptionPane.YES_OPTION) {
            String name = JOptionPane.showInputDialog(this, "参数名:");
            String value = JOptionPane.showInputDialog(this, "参数值:");
            if (name != null && value != null) {
                selected.add(new DefaultMutableTreeNode("Param name=\"" + name + "\" value=\"" + value + "\""));
            }
            option = JOptionPane.showConfirmDialog(this, "继续添加参数?", "参数", JOptionPane.YES_NO_OPTION);
        }
    }

    private void buildXML(DefaultMutableTreeNode node, StringBuilder xml, String indent) {
        String content = node.toString();//节点项 内容
        // 按空格分隔（一个或多个空格）
        String[] split = content.split("\\s+");
        String name = split[0];
        if (name.equals("Selector") || name.equals("Sequence") || name.equals("Parallel") || name.equals("ConditionDecorate")) {
            xml.append(indent).append("<").append(content.split(" ")[0]).append(">\n");
            for (int i = 0; i < node.getChildCount(); i++) {
                buildXML((DefaultMutableTreeNode) node.getChildAt(i), xml, indent + "    ");
            }
            xml.append(indent).append("</").append(content.split(" ")[0]).append(">\n");
        } else if (name.equals("Condition") || name.equals("Action")) {
            String[] parts = content.split(" class=\"");
            String tag = parts[0];
            String cls = parts[1].substring(0, parts[1].length() - 1);
            xml.append(indent).append("<").append(tag).append(" class=\"").append(cls);
            if (node.getChildCount() > 0) {
                xml.append("\">");
                xml.append("\n");
                for (int i = 0; i < node.getChildCount(); i++) {
                    String param = node.getChildAt(i).toString();
                    xml.append(indent).append("    <").append(param).append("/>").append("\n");
                }
                xml.append(indent).append("</").append(tag).append(">\n");
            } else {
                xml.append("\"/>\n");
            }
        }
    }

    private void saveToFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("保存 XML 文件");
        int userSelection = fileChooser.showSaveDialog(this);
        if (userSelection == JFileChooser.APPROVE_OPTION) {
            File fileToSave = fileChooser.getSelectedFile();
            try (FileWriter fw = new FileWriter(fileToSave)) {
                StringBuilder xml = new StringBuilder();
                buildXML(root, xml, "");
                fw.write(xml.toString());
                JOptionPane.showMessageDialog(this, "保存成功: " + fileToSave.getAbsolutePath());
            } catch (IOException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(this, "保存失败: " + ex.getMessage());
            }
        }
    }

    private void loadFromFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("加载 XML 文件");
        int userSelection = fileChooser.showOpenDialog(this);
        if (userSelection == JFileChooser.APPROVE_OPTION) {
            File fileToLoad = fileChooser.getSelectedFile();
            try {
                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(fileToLoad);
                doc.getDocumentElement().normalize();

                root = buildTreeFromElement(doc.getDocumentElement());
                treeModel.setRoot(root);
                tree.setModel(treeModel);
                JOptionPane.showMessageDialog(this, "加载成功: " + fileToLoad.getAbsolutePath());
            } catch (ParserConfigurationException | SAXException | IOException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(this, "加载失败: " + e.getMessage());
            }
        }
    }

    private DefaultMutableTreeNode buildTreeFromElement(Element element) {
        String tagName = element.getTagName();
        String classAttr = element.getAttribute("class");
        DefaultMutableTreeNode node;

        if (classAttr != null && !classAttr.isEmpty()) {
            node = new DefaultMutableTreeNode(tagName + " class=\"" + classAttr + "\"");
        } else {
            node = new DefaultMutableTreeNode(tagName);
        }

        NodeList children = element.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) child;
                if ("Param".equals(childElement.getTagName())) {
                    String name = childElement.getAttribute("name");
                    String value = childElement.getAttribute("value");
                    node.add(new DefaultMutableTreeNode("Param name=\"" + name + "\" value=\"" + value + "\""));
                } else {
                    node.add(buildTreeFromElement(childElement));
                }
            }
        }

        return node;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new BehaviorTreeEditor().setVisible(true));
    }
}

class TreeTransferHandler extends TransferHandler {
    private DataFlavor nodesFlavor;
    private DefaultMutableTreeNode[] nodesToRemove;

    public TreeTransferHandler() {
        try {
            String mimeType = DataFlavor.javaJVMLocalObjectMimeType +
                    ";class=\"" + DefaultMutableTreeNode[].class.getName() + "\"";
            nodesFlavor = new DataFlavor(mimeType);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public int getSourceActions(JComponent c) {
        return MOVE;
    }

    @Override
    protected Transferable createTransferable(JComponent c) {
        JTree tree = (JTree) c;
        TreePath[] paths = tree.getSelectionPaths();
        if (paths == null) return null;

        ArrayList<DefaultMutableTreeNode> copies = new ArrayList<>();
        ArrayList<DefaultMutableTreeNode> toRemove = new ArrayList<>();
        for (TreePath path : paths) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
            copies.add(cloneNode(node));
            toRemove.add(node);
        }

        nodesToRemove = toRemove.toArray(new DefaultMutableTreeNode[0]);
        return new NodesTransferable(copies.toArray(new DefaultMutableTreeNode[0]));
    }

    private DefaultMutableTreeNode cloneNode(DefaultMutableTreeNode node) {
        return new DefaultMutableTreeNode(node.getUserObject()); // 简化版，只复制一层
    }

    @Override
    public boolean canImport(TransferSupport support) {
        if (!support.isDrop()) return false;
        if (!support.isDataFlavorSupported(nodesFlavor)) return false;

        JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
        TreePath path = dl.getPath();
        return path != null;
    }

    @Override
    public boolean importData(TransferSupport support) {
        if (!canImport(support)) return false;

        JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
        TreePath dest = dl.getPath();
        int index = dl.getChildIndex();
        JTree tree = (JTree) support.getComponent();
        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
        DefaultMutableTreeNode parent = (DefaultMutableTreeNode) dest.getLastPathComponent();

        try {
            DefaultMutableTreeNode[] nodes = (DefaultMutableTreeNode[])
                    support.getTransferable().getTransferData(nodesFlavor);

            for (DefaultMutableTreeNode node : nodes) {
                model.insertNodeInto(node, parent,
                        (index == -1 ? parent.getChildCount() : index++));
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    @Override
    protected void exportDone(JComponent source, Transferable data, int action) {
        if (action == MOVE && nodesToRemove != null) {
            JTree tree = (JTree) source;
            DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
            for (DefaultMutableTreeNode node : nodesToRemove) {
                model.removeNodeFromParent(node);
            }
        }
    }

    class NodesTransferable implements Transferable {
        DefaultMutableTreeNode[] nodes;

        public NodesTransferable(DefaultMutableTreeNode[] nodes) {
            this.nodes = nodes;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{nodesFlavor};
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return nodesFlavor.equals(flavor);
        }

        @Override
        public Object getTransferData(DataFlavor flavor)
                throws UnsupportedFlavorException, IOException {
            if (!isDataFlavorSupported(flavor))
                throw new UnsupportedFlavorException(flavor);
            return nodes;
        }
    }
}


